
package com.zcp.wizard;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.xmlpull.v1.XmlPullParser;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.Xml;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.SocketTimeoutException;

public class UpdateUtils {
    private static String TAG = "UpdateUtils";

    private static Context mContext;

    private static int getVerCode(Context context) {
        int verCode = -1;
        try {
            verCode = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode;
        } catch (NameNotFoundException e) {
            Log.e(TAG, e.getMessage());
        }
        return verCode;
    }

    private static String getVerName(Context context) {
        String verName = "";
        try {
            verName = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
        } catch (NameNotFoundException e) {
            Log.e(TAG, e.getMessage());
        }
        return verName;
    }

    private static void doNewVersionUpdate(Context context, final VersionInfo versionInfo) {

        mContext = context;
        String verName = UpdateUtils.getVerName(context);
        StringBuffer sb = new StringBuffer();
        sb.append(context.getString(R.string.current_version));
        sb.append(verName);
        sb.append("," + context.getString(R.string.find_new_version));
        sb.append(versionInfo.versionName);
        sb.append("," + context.getString(R.string.version_size));
        sb.append(versionInfo.versionSize);
        sb.append("," + context.getString(R.string.should_update));
        Dialog dialog = new AlertDialog.Builder(context)
                .setTitle(context.getString(R.string.soft_update)).setMessage(sb.toString())
                // 设置内容
                .setPositiveButton(context.getString(R.string.update),// 设置确定按钮
                        new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                UpdateTask task = new UpdateTask(mContext);
                                task.execute(versionInfo);
                            }

                        })
                .setNegativeButton(context.getString(R.string.do_not_update),
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int whichButton) {
                                dialog.dismiss();
                            }
                        }).create();// 创建
        // 显示对话框
        dialog.show();
    }

    private static void notNewVersionShow(Context context) {
        String verName = UpdateUtils.getVerName(context);
        StringBuffer sb = new StringBuffer();
        sb.append(context.getString(R.string.current_version));
        sb.append(verName);
        sb.append("\n" + context.getString(R.string.last_version));
        Dialog dialog = new AlertDialog.Builder(context)
                .setTitle(context.getString(R.string.soft_update)).setMessage(sb.toString())// 设置内容
                .setPositiveButton(context.getString(R.string.ok),// 设置确定按钮
                        new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                            }

                        }).create();// 创建
        // 显示对话框
        dialog.show();
    }

    /**
     * 获取版本信息
     * 
     * @return
     * @throws Exception
     */
    private static VersionInfo getVersionInfo(Context context) {
        VersionInfo versionInfo = new VersionInfo();
        StringReader stringRead = null;
        XmlPullParser parser;
        try {
            
//            <?xml version="1.0" encoding="utf-8"?>
//            <wizard>
//            <apk name="wizard_v2.apk" versionCode="2" versionName="1.1" sizeStr="998KB" >http://www.ztewg.com/apk/wizard_v2.apk</apk>
//            </wizard>
            // 获取如上格式文件
            String verStr = getContent(Constants.UPDATE_SERVER);
            stringRead = new StringReader(verStr);
            parser = Xml.newPullParser();
            versionInfo = new VersionInfo();

            parser.setInput(stringRead);
            int event = parser.getEventType();// 产生第一个事件
            while (event != XmlPullParser.END_DOCUMENT) {
                switch (event) {
                    case XmlPullParser.START_TAG:// 判断当前事件是否是标签元素开始事件
                        if (parser.getName().equals("apk")) {
                            versionInfo.apkName = parser.getAttributeValue(null, "name");
                            versionInfo.versionName = parser.getAttributeValue(null, "versionName");                            
                            versionInfo.versionSize = parser.getAttributeValue(null, "sizeStr");
                            versionInfo.versionCode = Integer.valueOf(parser.getAttributeValue(
                                    null, "versionCode"));
                            versionInfo.updateUrl = parser.nextText();
                        }
                        break;
                }
                event = parser.next();// 进入下一个元素并触发相应事件
            }
            parser = null;
            if (stringRead != null) {
                stringRead.close();
                stringRead = null;
            }
        } catch (ConnectTimeoutException e) {
            versionInfo = null;
            Toast.makeText(context, R.string.connection_net_timeout, Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        } catch (SocketTimeoutException e) {
            versionInfo = null;
            Toast.makeText(context, R.string.connection_net_timeout, Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        } catch (Exception e) {
            versionInfo = null;
            Toast.makeText(context, R.string.can_not_connection_net, Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }
        return versionInfo;
    }

    private static Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            VersionInfo versionInfo = getVersionInfo(mContext);
            if (versionInfo == null) {
                return;
            }
            int currentVerCode = getVerCode(mContext);

            if (versionInfo.versionCode > currentVerCode) {
                if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                    doNewVersionUpdate(mContext, versionInfo);
                } else {
                    Toast.makeText(mContext, mContext.getString(R.string.can_not_use_sd),
                            Toast.LENGTH_LONG).show();
                }
            } else {
                notNewVersionShow(mContext);
            }
        }

    };

    public static void updateApp(Context context) {
        Toast.makeText(context, context.getString(R.string.check_new), Toast.LENGTH_SHORT).show();
        mContext = context;
        handler.sendEmptyMessageDelayed(0, 300);

    }

    /**
     * 获取网址内容
     * 
     * @param url
     * @return
     * @throws Exception
     */
    private static String getContent(String url) throws Exception {
        StringBuilder sb = new StringBuilder();

        HttpClient client = new DefaultHttpClient();
        HttpParams httpParams = client.getParams();
        // 设置网络超时参数
        HttpConnectionParams.setConnectionTimeout(httpParams, 3000);
        HttpConnectionParams.setSoTimeout(httpParams, 5000);
        HttpResponse response = client.execute(new HttpGet(url));
        if (response.getStatusLine().getStatusCode() == 200) {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(
                        entity.getContent(), "UTF-8"), 8192);

                String line = null;
                while ((line = reader.readLine()) != null) {
                    sb.append(line + "\n");
                }
                reader.close();
            }
        } else {
            Log.i(TAG, "get fail");
        }
        return sb.toString();
    }

    private static class UpdateTask extends AsyncTask<VersionInfo, Integer, String> {

        private Context mContext;

        ProgressDialog dialog;

        UpdateTask(Context context) {
            mContext = context;
        }

        @Override
        protected void onPostExecute(String result) {
            dialog.dismiss();
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(
                    Uri.fromFile(new File(Environment.getExternalStorageDirectory(), result)),
                    "application/vnd.android.package-archive");
            mContext.startActivity(intent);
            super.onPostExecute(result);
        }

        @Override
        protected void onPreExecute() {
            dialog = new ProgressDialog(mContext);
            dialog.setMessage(mContext.getString(R.string.loading));
            dialog.setIndeterminate(false);
            dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            dialog.setCancelable(true);
            dialog.setOnCancelListener(new OnCancelListener() {

                @Override
                public void onCancel(DialogInterface dialog) {
                    UpdateTask.this.cancel(true);
                    dialog.cancel();
                }
            });
            dialog.show();
            super.onPreExecute();
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            dialog.setProgress(values[0]);
            super.onProgressUpdate(values);
        }

        InputStream is;

        @Override
        protected String doInBackground(VersionInfo... params) {
            HttpClient client = new DefaultHttpClient();

            VersionInfo versionInfo = params[0];
            HttpGet get = new HttpGet(versionInfo.updateUrl);
            HttpResponse response;
            try {
                response = client.execute(get);

                HttpEntity entity = response.getEntity();

                long length = entity.getContentLength();
                dialog.setMax((int) (length / 1024));
                is = entity.getContent();
                FileOutputStream fileOutputStream = null;

                if (is != null) {
                    File file = new File(Environment.getExternalStorageDirectory(),
                            versionInfo.apkName);
                    fileOutputStream = new FileOutputStream(file);
                    byte[] buf = new byte[1024];
                    int ch = -1;
                    int count = 0;
                    while ((ch = is.read(buf)) != -1) {
                        if (isCancelled()) {
                            break;
                        }
                        fileOutputStream.write(buf, 0, ch);
                        count += ch;
                        publishProgress((int) (count / 1024));
                    }

                }
                fileOutputStream.flush();
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }

            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (is != null) {
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

            return versionInfo.apkName;
        }

    }

    private static class VersionInfo {
        String apkName;

        String versionName;
        
        String versionSize;

        int versionCode;

        String updateUrl;
    }

}
